package gui;

import java.awt.event.ActionListener;

import javax.swing.JFrame;

import model.DataSet;
import api.GUIapi;

import javax.swing.JPanel;

import java.awt.BorderLayout;
import java.awt.GridLayout;

import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
import javax.swing.JList;
import javax.swing.JButton;
import javax.swing.UnsupportedLookAndFeelException;

import java.awt.Font;

import javax.swing.SwingConstants;
import javax.swing.BoxLayout;

import java.awt.FlowLayout;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.Insets;

import javax.swing.JProgressBar;
import javax.swing.border.TitledBorder;
import javax.swing.UIManager;

import java.awt.Color;

import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.text.JTextComponent;

import java.awt.event.ActionEvent;
import java.io.File;
import java.util.ArrayList;

import javax.swing.AbstractListModel;
import javax.swing.ListSelectionModel;
import javax.swing.JScrollPane;
import javax.swing.JSlider;

public class ApplicationWindow implements GUIapi {

	private final String[] ATTACK_TYPES_TRAINING = new String[] { "back",
			"buffer_overflow", "ftp_write", "guess_passwd", "imap", "ipsweep",
			"land", "loadmodule", "multihop", "neptune", "nmap", "perl", "phf",
			"pod", "portsweep", "rootkit", "satan", "smurf", "spy", "teardrop",
			"warezclient", "warezmaster" };

	private final String[] ATTACK_TYPES_TEST = new String[] { "snmpgetattack",
			"named", "xlock", "smurf", "ipsweep", "multihop", "xsnoop",
			"sendmail", "guess_passwd", "saint", "buffer_overflow",
			"portsweep", "pod", "apache2", "phf", "udpstorm", "warezmaster",
			"perl", "satan", "xterm", "mscan", "processtable", "ps", "nmap",
			"rootkit", "neptune", "loadmodule", "imap", "back", "httptunnel",
			"worm", "mailbomb", "ftp_write", "teardrop", "land", "sqlattack",
			"snmpguess"

	};

	private JFrame frmKddDataset;
	private JPanel argumentsPanel;
	private JTextField nameTextFieldTR;
	private JTextField sizeTextFieldTR;
	private JTextField nameTextFieldTS;
	private JTextField sizeTextFieldTS;
	private JTextField chooseFileTextFieldTR;
	private JButton runButton;
	private JList<String> listTypesOfConnectionTR;
	private JList<String> listTypesOfConnectionTS;
	private JProgressBar progressBar;
	private JSlider percentageSliderTR;
	private JSlider percentageSliderTS;
	private JLabel sliderLabelTR;
	private JLabel sliderLabelTS;
	private JButton chooseFileButtonTR;
	private JButton chooseFileButtonTS;
	private JTextField chooseFileTextFieldTS;
	private ArrayList<JComponent> disableWhileRunning = new ArrayList<JComponent>();

	/**
	 * Initialize the contents of the frame.
	 * 
	 * @wbp.parser.entryPoint
	 */
	private void initialize() {
		frmKddDataset = new JFrame();
		frmKddDataset.setTitle("KDD 1999 Data-Set Splitter");
		frmKddDataset.setBounds(100, 100, 500, 600);
		frmKddDataset.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		} catch (ClassNotFoundException | InstantiationException
				| IllegalAccessException | UnsupportedLookAndFeelException e) {
			e.printStackTrace();
		}

		JPanel containerPanel = new JPanel();
		containerPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
		frmKddDataset.getContentPane().add(containerPanel, BorderLayout.CENTER);
		containerPanel.setLayout(new BorderLayout(0, 0));

		JPanel operationPanel = new JPanel();
		containerPanel.add(operationPanel, BorderLayout.SOUTH);
		operationPanel.setLayout(new GridLayout(2, 0, 0, 0));

		JPanel runPanel = new JPanel();
		operationPanel.add(runPanel);
		runPanel.setBorder(new EmptyBorder(15, 100, 15, 100));
		runPanel.setLayout(new GridLayout(0, 1, 0, 0));

		runButton = new JButton("Create Data Sets");
		runPanel.add(runButton);

		JPanel loadPanel = new JPanel();
		operationPanel.add(loadPanel);
		loadPanel.setLayout(new BorderLayout(0, 0));

		progressBar = new JProgressBar();
		progressBar.setMinimum(0);
		progressBar.setMaximum(100);
		loadPanel.add(progressBar, BorderLayout.CENTER);
		progressBar.setStringPainted(true);

		argumentsPanel = new JPanel();
		containerPanel.add(argumentsPanel, BorderLayout.CENTER);
		argumentsPanel.setLayout(new GridLayout(2, 1, 0, 0));

		JPanel panelArgumentsTraining = new JPanel();
		panelArgumentsTraining.setBorder(new TitledBorder(null,
				"Training Data-Set Values", TitledBorder.LEADING,
				TitledBorder.TOP, new Font("tahoma", Font.BOLD, 15), null));
		argumentsPanel.add(panelArgumentsTraining);
		panelArgumentsTraining.setLayout(new GridLayout(3, 1, 0, 0));

		JPanel fileChooserPanelTR = new JPanel();
		panelArgumentsTraining.add(fileChooserPanelTR);
		fileChooserPanelTR.setBorder(new EmptyBorder(15, 15, 15, 20));
		fileChooserPanelTR.setLayout(new GridLayout(0, 2, 5, 0));

		chooseFileTextFieldTR = new JTextField();
		chooseFileTextFieldTR.setFont(new Font("Tahoma", Font.PLAIN, 14));
		fileChooserPanelTR.add(chooseFileTextFieldTR);
		chooseFileTextFieldTR.setColumns(10);

		chooseFileButtonTR = new JButton("Choose File");
		chooseFileButtonTR.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				JFileChooser chooser = new JFileChooser();
				int returnVal = chooser.showDialog(frmKddDataset,
						"Choose Data-Set to Work With");
				if (returnVal == JFileChooser.APPROVE_OPTION) {
					chooseFileTextFieldTR.setText(chooser.getSelectedFile()
							.getAbsolutePath());
				}
			}
		});
		fileChooserPanelTR.add(chooseFileButtonTR);

		JPanel panelLabelsTR = new JPanel();
		panelArgumentsTraining.add(panelLabelsTR);
		panelLabelsTR.setLayout(new GridLayout(0, 4, 0, 0));

		JLabel nameLabelTraining = new JLabel("Nome");
		nameLabelTraining.setFont(new Font("Tahoma", Font.BOLD, 11));
		nameLabelTraining.setHorizontalAlignment(SwingConstants.CENTER);
		panelLabelsTR.add(nameLabelTraining);

		JLabel sizeLabelTraining = new JLabel("Tamanho(N\u00BA Conex\u00F5es)");
		sizeLabelTraining.setHorizontalAlignment(SwingConstants.CENTER);
		panelLabelsTR.add(sizeLabelTraining);

		JLabel typesOfConnectionLabelTR = new JLabel("Tipos De Conex\u00F5es");
		typesOfConnectionLabelTR.setHorizontalAlignment(SwingConstants.CENTER);
		panelLabelsTR.add(typesOfConnectionLabelTR);

		JLabel percentageNormalConnectionLabelTR = new JLabel(
				"% de Conex\u00F5es Normais");
		percentageNormalConnectionLabelTR
				.setHorizontalAlignment(SwingConstants.CENTER);
		panelLabelsTR.add(percentageNormalConnectionLabelTR);

		JPanel panelValuesTR = new JPanel();
		panelArgumentsTraining.add(panelValuesTR);
		panelValuesTR.setLayout(new GridLayout(0, 4, 0, 0));

		nameTextFieldTR = new JTextField();
		nameTextFieldTR.setFont(new Font("Tahoma", Font.PLAIN, 17));
		panelValuesTR.add(nameTextFieldTR);
		nameTextFieldTR.setColumns(10);

		sizeTextFieldTR = new JTextField();
		sizeTextFieldTR.setFont(new Font("Tahoma", Font.PLAIN, 17));
		panelValuesTR.add(sizeTextFieldTR);
		sizeTextFieldTR.setColumns(10);

		listTypesOfConnectionTR = new JList<String>();
		listTypesOfConnectionTR.setModel(new AbstractListModel<String>() {
			String[] values = ATTACK_TYPES_TRAINING;

			public int getSize() {
				return values.length;
			}

			public String getElementAt(int index) {
				return values[index];
			}
		});

		JScrollPane scrollPane = new JScrollPane(listTypesOfConnectionTR);
		panelValuesTR.add(scrollPane);

		JPanel sliderPanelTR = new JPanel();
		panelValuesTR.add(sliderPanelTR);
		sliderPanelTR.setLayout(new BorderLayout(0, 0));

		sliderLabelTR = new JLabel("100%");
		sliderLabelTR.setFont(new Font("Tahoma", Font.PLAIN, 14));
		sliderLabelTR.setHorizontalAlignment(SwingConstants.CENTER);
		sliderPanelTR.add(sliderLabelTR, BorderLayout.NORTH);

		percentageSliderTR = new JSlider();
		sliderPanelTR.add(percentageSliderTR);
		percentageSliderTR.setSnapToTicks(true);
		percentageSliderTR.setMajorTickSpacing(15);
		percentageSliderTR.setMinorTickSpacing(1);
		percentageSliderTR.setValue(100);
		percentageSliderTR.setPaintLabels(true);
		percentageSliderTR.setPaintTicks(true);

		percentageSliderTR.addChangeListener(new ChangeListener() {

			@Override
			public void stateChanged(ChangeEvent arg0) {
				sliderLabelTR.setText(Integer.toString(percentageSliderTR
						.getValue()) + "%");
			}
		});

		JPanel panelArgumentsTest = new JPanel();
		panelArgumentsTest.setBorder(new TitledBorder(null,
				"Test Data-Set Values", TitledBorder.LEADING, TitledBorder.TOP,
				new Font("tahoma", Font.BOLD, 15), null));
		argumentsPanel.add(panelArgumentsTest);
		panelArgumentsTest.setLayout(new GridLayout(0, 1, 0, 0));

		JPanel fileChooserPanelTS = new JPanel();
		fileChooserPanelTS.setBorder(new EmptyBorder(15, 15, 15, 20));
		panelArgumentsTest.add(fileChooserPanelTS);
		fileChooserPanelTS.setLayout(new GridLayout(0, 2, 5, 0));

		chooseFileTextFieldTS = new JTextField();
		chooseFileTextFieldTS.setFont(new Font("Tahoma", Font.PLAIN, 14));
		chooseFileTextFieldTS.setColumns(10);
		fileChooserPanelTS.add(chooseFileTextFieldTS);

		chooseFileButtonTS = new JButton("Choose File");
		chooseFileButtonTS.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				JFileChooser chooser = new JFileChooser();
				int returnVal = chooser.showDialog(frmKddDataset,
						"Choose Data-Set to Work With");
				if (returnVal == JFileChooser.APPROVE_OPTION) {
					chooseFileTextFieldTS.setText(chooser.getSelectedFile()
							.getAbsolutePath());
				}
			}
		});
		fileChooserPanelTS.add(chooseFileButtonTS);

		JPanel panelLabelsTS = new JPanel();
		panelArgumentsTest.add(panelLabelsTS);
		panelLabelsTS.setLayout(new GridLayout(0, 4, 0, 0));

		JLabel nameLabelTest = new JLabel("Nome");
		nameLabelTest.setHorizontalAlignment(SwingConstants.CENTER);
		panelLabelsTS.add(nameLabelTest);

		JLabel sizeLabelTest = new JLabel("Tamanho(N\u00BA Conex\u00F5es)");
		sizeLabelTest.setHorizontalAlignment(SwingConstants.CENTER);
		panelLabelsTS.add(sizeLabelTest);

		JLabel typesOfConnectionLabelTS = new JLabel("Tipos De Conex\u00F5es");
		typesOfConnectionLabelTS.setHorizontalAlignment(SwingConstants.CENTER);
		panelLabelsTS.add(typesOfConnectionLabelTS);

		JLabel percentageOfNormalConnectionLabelTS = new JLabel(
				"% de Conex\u00F5es Normais");
		percentageOfNormalConnectionLabelTS
				.setHorizontalAlignment(SwingConstants.CENTER);
		panelLabelsTS.add(percentageOfNormalConnectionLabelTS);

		JPanel panelValuesTS = new JPanel();
		panelArgumentsTest.add(panelValuesTS);
		panelValuesTS.setLayout(new GridLayout(0, 4, 0, 0));

		nameTextFieldTS = new JTextField();
		nameTextFieldTS.setFont(new Font("Tahoma", Font.PLAIN, 17));
		nameTextFieldTS.setColumns(10);
		panelValuesTS.add(nameTextFieldTS);

		sizeTextFieldTS = new JTextField();
		sizeTextFieldTS.setFont(new Font("Tahoma", Font.PLAIN, 17));
		sizeTextFieldTS.setColumns(10);
		panelValuesTS.add(sizeTextFieldTS);

		listTypesOfConnectionTS = new JList<String>();
		listTypesOfConnectionTS.setModel(new AbstractListModel<String>() {
			String[] values = ATTACK_TYPES_TEST;

			public int getSize() {
				return values.length;
			}

			public String getElementAt(int index) {
				return values[index];
			}
		});

		JScrollPane scrollPane_1 = new JScrollPane(listTypesOfConnectionTS);
		panelValuesTS.add(scrollPane_1);

		JPanel sliderPanelTS = new JPanel();
		panelValuesTS.add(sliderPanelTS);
		sliderPanelTS.setLayout(new BorderLayout(0, 0));

		sliderLabelTS = new JLabel("100%");
		sliderLabelTS.setHorizontalAlignment(SwingConstants.CENTER);
		sliderLabelTS.setFont(new Font("Tahoma", Font.PLAIN, 14));
		sliderPanelTS.add(sliderLabelTS, BorderLayout.NORTH);

		percentageSliderTS = new JSlider();
		sliderPanelTS.add(percentageSliderTS);
		percentageSliderTS.setSnapToTicks(true);
		percentageSliderTS.setMinorTickSpacing(1);
		percentageSliderTS.setMajorTickSpacing(15);
		percentageSliderTS.setPaintTicks(true);
		percentageSliderTS.setPaintLabels(true);
		percentageSliderTS.setValue(100);
		percentageSliderTS.addChangeListener(new ChangeListener() {

			@Override
			public void stateChanged(ChangeEvent arg0) {
				sliderLabelTS.setText(Integer.toString(percentageSliderTS
						.getValue()) + "%");
			}
		});
		disableWhileRunning.add(chooseFileButtonTR);
		disableWhileRunning.add(chooseFileTextFieldTR);
		disableWhileRunning.add(chooseFileButtonTS);
		disableWhileRunning.add(chooseFileTextFieldTS);
		disableWhileRunning.add(listTypesOfConnectionTR);
		disableWhileRunning.add(listTypesOfConnectionTS);
		disableWhileRunning.add(nameTextFieldTR);
		disableWhileRunning.add(nameTextFieldTS);
		disableWhileRunning.add(percentageSliderTR);
		disableWhileRunning.add(percentageSliderTS);
		disableWhileRunning.add(sizeTextFieldTR);
		disableWhileRunning.add(sizeTextFieldTS);
		disableWhileRunning.add(runButton);
	}

	@Override
	public void initGUI() {
		initialize();
		frmKddDataset.setVisible(true);
	}

	@Override
	public void addListener(ActionListener l) {
		runButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				if (validate()) {
					lockInputs();
					l.actionPerformed(arg0);
				}
			}
		});
	}

	private void unlockInputs() {
		for (JComponent component : disableWhileRunning) {
			component.setEnabled(true);
		}
	}

	private void lockInputs() {
		for (JComponent component : disableWhileRunning) {
			component.setEnabled(false);
		}
	}

	private boolean validate() {
		File file = new File(chooseFileTextFieldTR.getText());
		if (!file.exists()) {
			JOptionPane.showMessageDialog(frmKddDataset,
					"Choosen File for training set does not exist.",
					"File Error", JOptionPane.ERROR_MESSAGE);
			return false;
		}
		file = new File(chooseFileTextFieldTS.getText());
		if (!file.exists()) {
			JOptionPane.showMessageDialog(frmKddDataset,
					"Choosen File for test set does not exist.", "File Error",
					JOptionPane.ERROR_MESSAGE);
			return false;
		}
		if (nameTextFieldTR.getText().equals("")
				|| sizeTextFieldTR.getText().equals("")) {
			JOptionPane.showMessageDialog(frmKddDataset,
					"Some fields are missing information in the training set.",
					"Training Set Error", JOptionPane.ERROR_MESSAGE);
			return false;
		}
		if (nameTextFieldTS.getText().equals("")
				|| sizeTextFieldTS.getText().equals("")) {
			JOptionPane.showMessageDialog(frmKddDataset,
					"Some fields are missing information in the test set.",
					"Test Set Error", JOptionPane.ERROR_MESSAGE);
			return false;
		}
		if (!sizeTextFieldTR.getText().matches("^\\d+$")) {
			JOptionPane.showMessageDialog(frmKddDataset,
					"The size of the training set must be and integer",
					"Training Set Error", JOptionPane.ERROR_MESSAGE);
			return false;
		}
		if (!sizeTextFieldTS.getText().matches("^\\d+$")) {
			JOptionPane.showMessageDialog(frmKddDataset,
					"The size of the test set must be and integer",
					"Test Set Error", JOptionPane.ERROR_MESSAGE);
			return false;
		}

		if (nameTextFieldTR.getText().equals(nameTextFieldTS.getText())) {
			JOptionPane.showMessageDialog(frmKddDataset,
					"The names of the training and test set can't be the same",
					"Naming error", JOptionPane.ERROR_MESSAGE);
			return false;
		}

		return true;
	}

	@Override
	public DataSet getTrainingDataSet() {
		DataSet training = new DataSet(Integer.parseInt(sizeTextFieldTR
				.getText()), percentageSliderTR.getValue(),
				chooseFileTextFieldTR.getText());
		training.setTrainingFileName(nameTextFieldTR.getText());
		for (int i = 0; i < listTypesOfConnectionTR.getSelectedValuesList()
				.size(); i++) {
			training.addTipoConeccao((String) listTypesOfConnectionTR
					.getSelectedValuesList().get(i));
		}
		return training;
	}

	@Override
	public DataSet getTestDataSet() {
		DataSet test = new DataSet(Integer.parseInt(sizeTextFieldTS.getText()),
				percentageSliderTS.getValue(), chooseFileTextFieldTS.getText());
		test.setTrainingFileName(nameTextFieldTS.getText());
		for (int i = 0; i < listTypesOfConnectionTS.getSelectedValuesList()
				.size(); i++) {
			test.addTipoConeccao((String) listTypesOfConnectionTS
					.getSelectedValuesList().get(i));
		}
		return test;
	}

	@Override
	public void setProgressValue(int percentagem) {
		if (progressBar.getValue() == 100) {
			progressBar.setValue(0);
		}
		progressBar.setValue(percentagem);

	}

	@Override
	public void showMessage(String message) {
		if (message.length() == 0) {
			JOptionPane.showMessageDialog(this.frmKddDataset,
					"Concluido sem erros!! ;)");
		} else {
			JOptionPane.showMessageDialog(this.frmKddDataset, message,
					"Warning", JOptionPane.WARNING_MESSAGE);
		}

		unlockInputs();

	}
}
